///<reference path="../index.d.ts"/>
import _ from "lodash";
import { REDIS_KEY } from "../declare/keys";
import { getRedisClient } from "../library/redis";
import { BaseTask } from "./BaseTask";
const SystemConfig = require("../config/system.json");
const NODE_ENV = process.env.NODE_ENV || "development";
const WATCHING_LIMTED = SystemConfig[NODE_ENV]["watching_limted"];
import Aclient from "ac-danmu";
import {
  updataLiverGiftData,
  updateDanmakuData,
  updateLiverData,
} from "../business/updateLiverData";
import { Danmaku, Gift } from "../declare/liver";

const CLIENT_LIST: { acClient: any; roomId: number }[] = [];
export class WatchingRoomDataProcess implements BaseTask {
  runningInterval: NodeJS.Timeout | null = null;
  redisClient = getRedisClient();
  constructor() {
    this.runningInterval = setInterval(this.runTask.bind(this), 5000);
  }
  public async runTask() {
    if (this.runningInterval) {
      clearInterval(this.runningInterval);
      this.runningInterval = null;
    }
    let roomid = await this.redisClient.lpop(
      REDIS_KEY.REDIS_QUEUE_NOW_UN_WATCHING_ROOM
    );
    while (roomid) {
      await this.watchRoomProcess(Number(roomid));
      roomid = await this.redisClient.lpop(
        REDIS_KEY.REDIS_QUEUE_NOW_UN_WATCHING_ROOM
      );
    }

    this.runningInterval = setInterval(this.runTask.bind(this), 5000);
  }

  public async watchRoomProcess(roomId: number) {
    //排他锁
    const lock = await this.redisClient.get(
      `${REDIS_KEY.REDIS_ROOMID_LOCK_PREFIX}:${roomId}`
    );
    if (lock === "1") return;
    if (CLIENT_LIST.length >= WATCHING_LIMTED) return;
    await this.redisClient.set(
      `${REDIS_KEY.REDIS_ROOMID_LOCK_PREFIX}:${roomId}`,
      "1"
    );
    await this.watchingRoom(roomId);
  }

  public async watchingRoom(roomId: number) {
    try {
      await updateLiverData(roomId);
      const acClient = await Aclient(roomId, { login: false });
      if (!acClient) return this.endingLive(roomId);
      acClient.wsStart();
      acClient.on("enter", async () => {
        console.log("entered", roomId);
        await this.redisClient.sadd(
          REDIS_KEY.REDIS_KEY_NOW_WATCHING_ROOM,
          roomId
        );
      });
      acClient.on('danmaku',(danmamu:Danmaku)=>{
        updateDanmakuData(danmamu,roomId);
      })
      acClient.on("gift", async (gift: Gift) => {
        if (gift.giftName === "香蕉") return;
       await updataLiverGiftData(gift, roomId);
      });
      acClient.on("liveclose", async () => {
        await this.endingLive(roomId);
      });
      acClient.on("decode-error", async () => {
        await this.endingLive(roomId);
      });
      CLIENT_LIST.push({ acClient, roomId });
    } catch (error) {
      console.log(error);
      await this.endingLive(roomId);
      return;
    }
  }
  private async endingLive(roomId: number) {
    await Promise.all([
      this.redisClient.del(`${REDIS_KEY.REDIS_ROOMID_LOCK_PREFIX}:${roomId}`),
      this.redisClient.srem(REDIS_KEY.REDIS_KEY_NOW_WATCHING_ROOM, roomId),
    ]);
    _.remove(CLIENT_LIST, function (n) {
      if (n.roomId == roomId)
        n.acClient = null;
      return n.roomId == roomId;
    });
  }
}
